Análisis Inferencial de la Satisfacción Turística

Alumna: Erika Samara Alvares Angelim

Profesor: Gustavo Néstor Fontana Riera

Asignatura: Análisis e Interpretación de Datos

Fecha: 19 de junio de 2025

1 Introducción

Este cuaderno desarrolla el análisis estadístico inferencial de datos del sector turístico, en el marco de la Actividad 3. Se abordan dos preguntas:

  • 1️ ¿La satisfacción turística media general supera un valor de referencia?
  • 2️⃣ ¿Existen diferencias de satisfacción entre turistas con y sin necesidades de accesibilidad?

La variable satisfaction se mide en escala Likert de 1 a 5. Aunque se trata de una escala ordinal, se considera cuasi-continua y se trata como numérica, lo cual permite aplicar técnicas como t-test y análisis de correlación, tal como se justifica en estudios previos (Joshi et al., 2015).

El dataset original se encuentra en Kaggle: Cultural Tourism Dataset. Contiene registros simulados sobre turistas, preferencias, rutas, accesibilidad y evaluación de servicios como realidad virtual (VR).

También se incluirán análisis exploratorios, transformaciones y visualizaciones intermedias para enriquecer las conclusiones.


options(scipen = 999)  # Desactiva la notación científica

2 Carga de paquetes necesarios

Se utiliza pacman para instalar y cargar de forma más eficiente múltiples paquetes necesarios. Esta librería evita errores por duplicidad y permite mantener el código limpio.

if (!require("pacman")) install.packages("pacman")
pacman::p_load(
  tidyverse,         # Manipulación y visualización de datos
  skimr,             # Resumen estadístico completo con histogramas
  kableExtra,        # Tablas HTML más estéticas
  janitor,           # Limpieza de nombres de columnas
  modeest,           # Cálculo de la moda
  raster,            # Cálculo del coeficiente de variación
  moments,           # Asimetría y curtosis
  ggcorrplot,        # Mapa de calor de correlaciones
  corrplot,          # Mapa de calor de correlaciones  
  readr,             # Lectura de CSV
  ggplot2,           # Gráficos
  dplyr,             # Manipulación de datos
  stringr,           # Operaciones con texto (útil para limpiar intereses)
  moderndive,
  nycflights13
)

ℹ️ Evitamos conflictos con library() y require().


3 Carga y limpieza inicial de los datos

3.1 Cargar datos desde URL pública

# Cargar el dataset directamente desde GitHub
url_datos <- "https://raw.githubusercontent.com/ea-analisisdatos/unir/refs/heads/main/datos/tourism_dataset_5000.csv"
datos <- read_csv(url_datos)

3.2 Visualizar primeras líneas del dataset original

head(datos, 5) # mostra las primeras 5 filas del dataframe

ℹ️ Observa también que no se muestran todas las columnas. Puedes pulsar el ícono de “flecha ▶️” en la esquina superior derecha de la tabla para explorarlas.

# Verificar nombres de columnas
columnas <- colnames(datos)
columnas
##  [1] "Tourist ID"              "Age"                    
##  [3] "Interests"               "Preferred Tour Duration"
##  [5] "Accessibility"           "Site Name"              
##  [7] "Sites Visited"           "Tour Duration"          
##  [9] "Route ID"                "Tourist Rating"         
## [11] "System Response Time"    "Recommendation Accuracy"
## [13] "VR Experience Quality"   "Satisfaction"

ℹ️ Los nombres de columnas incluyen espacios, lo que puede dificultar el trabajo en R.


4 🧹 Limpieza de datos

4.1 Limpieza de nombres de columnas

Este paso, janitor convierte los nombres compuestos de las columnas en formato snake_case, sin espacios ni símbolos, facilitando su uso en R.

datos <- janitor::clean_names(datos)
head(datos, 5)

ℹ️ Puedes pulsar el ícono de “flecha ▶️” en la esquina superior derecha de la tabla HTML para explorarlas.

# Verificar nombres de columnas despues de la limpieza
columnas <- colnames(datos)
columnas
##  [1] "tourist_id"              "age"                    
##  [3] "interests"               "preferred_tour_duration"
##  [5] "accessibility"           "site_name"              
##  [7] "sites_visited"           "tour_duration"          
##  [9] "route_id"                "tourist_rating"         
## [11] "system_response_time"    "recommendation_accuracy"
## [13] "vr_experience_quality"   "satisfaction"

4.2 Convertir las columnas route_id a factor (variable categórica)

datos <- datos %>%
  mutate(route_id = as.factor(route_id))

4.3 Convertir las columnas tourist_id a factor (variable categórica)

datos <- datos %>%
  mutate(tourist_id = as.factor(tourist_id))

ℹ️ Aunque tienen valores numéricos, tourist_id y route_id son identificadores sin sentido ordinal. Por tanto, deben tratarse como factores.


4.4 Limpieza y descomposición de la columna interests

# Limpiar caracteres especiales y descomponer en filas
intereses_limpios <- datos %>%
  mutate(interests = str_replace_all(interests, "\\[|\\]|‘|’|'|\"", "")) %>%  # elimina caracteres extraños
  separate_rows(interests, sep = ",\\s*") %>%                                 # divide por comas
  mutate(interests = str_trim(interests)) %>%                                 # quita espacios
  count(interests, sort = TRUE)                                               # cuenta ocurrencias

ℹ️ Comentario técnico: separate_rows() descompone listas multivaluadas creando una nueva fila por cada elemento de interés individual. El dataframe final muestra una fila por cada categoría de interés única con su frecuencia total consolidada.


5 Estructura general del dataset

5.1 Consideraciones sobre los tipos de variables

Aunque varias variables del dataset están codificadas como numéricas, en realidad representan escalas ordinales, como ocurre con:

  • satisfaction: Satisfacción general (escala Likert 1–5)
  • tourist_rating: Valoración del turista (escala Likert 1–5)
  • vr_experience_quality: Calidad de la experiencia VR (escala Likert 1–5)
  • recommendation_accuracy: Precisión del sistema (0–100, asimilable a escala continua)
  • preferred_tour_duration: Preferencia en duración de tours (en días)

Estas variables mantienen un orden lógico entre categorías, pero no necesariamente equidistante. Sin embargo, en análisis estadísticos como:

  • Test t de Student (para comparar medias)
  • Correlaciones de Pearson (entre variables)

… es común y aceptado tratar escalas ordinales con más de 3 categorías como cuantitativas (de intervalo), especialmente si están bien distribuidas.

  • En este estudio, se tratarán como numéricas para aprovechar los métodos inferenciales, pero se dejará constancia de su naturaleza ordinal.
  • Esto se justifica ampliamente en literatura estadística aplicada (Boone & Boone, 2012; Joshi et al., 2015) cuando se asume que las distancias entre valores en escalas ordinales son equidistantes y se desea realizar análisis paramétricos.
# Cómo están estructurados los datos internamente
glimpse(datos)
## Rows: 5,000
## Columns: 14
## $ tourist_id              <fct> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,…
## $ age                     <dbl> 48, 37, 43, 46, 53, 50, 61, 23, 34, 61, 27, 37…
## $ interests               <chr> "['Architecture', 'Art', 'History']", "['Cultu…
## $ preferred_tour_duration <dbl> 5, 6, 6, 8, 5, 4, 7, 5, 5, 5, 4, 3, 8, 8, 4, 7…
## $ accessibility           <lgl> FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE,…
## $ site_name               <chr> "Eiffel Tower", "Colosseum", "Machu Picchu", "…
## $ sites_visited           <chr> "['Eiffel Tower', 'Great Wall of China', 'Taj …
## $ tour_duration           <dbl> 7, 1, 2, 5, 7, 4, 6, 2, 6, 6, 6, 5, 6, 1, 6, 8…
## $ route_id                <fct> 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000…
## $ tourist_rating          <dbl> 1.6, 2.6, 1.7, 2.0, 3.7, 2.2, 4.1, 2.8, 4.0, 3…
## $ system_response_time    <dbl> 3.73, 2.89, 2.22, 2.34, 2.00, 3.74, 4.66, 4.84…
## $ recommendation_accuracy <dbl> 97, 90, 94, 92, 96, 99, 93, 91, 95, 95, 99, 10…
## $ vr_experience_quality   <dbl> 4.5, 4.5, 4.7, 4.7, 4.8, 4.5, 4.5, 4.9, 4.4, 4…
## $ satisfaction            <dbl> 3, 3, 3, 3, 4, 3, 4, 3, 4, 4, 3, 3, 3, 4, 3, 3…

ℹ️ glimpse() ofrece una descripción compacta: tipo de cada columna, primeras observaciones y estructuras.

5.2 Verificación de tipos de variables

# Tabla con tipos de datos
tabla_variables <- tibble(
  Variable = names(datos),
  Tipo = sapply(datos, function(x) class(x)[1])
)
kable(tabla_variables, format = "html", caption = "Tipos de variables") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover", "condensed"))
Tipos de variables
Variable Tipo
tourist_id factor
age numeric
interests character
preferred_tour_duration numeric
accessibility logical
site_name character
sites_visited character
tour_duration numeric
route_id factor
tourist_rating numeric
system_response_time numeric
recommendation_accuracy numeric
vr_experience_quality numeric
satisfaction numeric

5.3 Diccionario de datos

Este diccionario ayuda a interpretar cada columna del dataset original. Algunas variables presentan valores de tipo ordinal, como escalas Likert de 1 a 5.

Diccionario de datos
Variable Descripción
tourist_id Identificador único del turista
age Edad del turista
interests Temas de interés
preferred_tour_duration Duración preferida del tour (días)
accessibility Requiere accesibilidad (TRUE/FALSE)
site_name Nombre del sitio visitado
sites_visited Lista de sitios visitados
tour_duration Duración del tour realizado
route_id ID de la ruta turística
tourist_rating Valoración del turista (1-5)
system_response_time Tiempo de respuesta del sistema
recommendation_accuracy Precisión de recomendaciones (%)
vr_experience_quality Calidad de experiencia VR (1-5)
satisfaction Satisfacción general (1-5)

6 Evaluación de calidad y estadísticos descriptivos

6.1 Resumen general con skimr

skimr muestra tipo de variable, valores únicos, media, desviación, y distribución en mini histograma. Ideal para descripción exploratoria.

# Análisis descriptivo rápido
skim(datos)
Data summary
Name datos
Number of rows 5000
Number of columns 14
_______________________
Column type frequency:
character 3
factor 2
logical 1
numeric 8
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
interests 0 1 7 39 0 85 0
site_name 0 1 9 19 0 5 0
sites_visited 0 1 13 55 0 85 0

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
tourist_id 0 1 FALSE 5000 1: 1, 2: 1, 3: 1, 4: 1
route_id 0 1 FALSE 5000 100: 1, 200: 1, 300: 1, 400: 1

Variable type: logical

skim_variable n_missing complete_rate mean count
accessibility 0 1 0.49 FAL: 2531, TRU: 2469

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
age 0 1 43.89 15.27 18.0 30.00 44.00 57.00 70 ▇▇▇▇▇
preferred_tour_duration 0 1 5.52 1.71 3.0 4.00 6.00 7.00 8 ▇▃▅▅▅
tour_duration 0 1 3.98 2.00 1.0 2.00 4.00 5.00 9 ▆▇▃▅▁
tourist_rating 0 1 3.00 1.16 1.0 2.00 3.00 4.00 5 ▇▇▇▇▇
system_response_time 0 1 3.24 1.02 1.5 2.36 3.23 4.13 5 ▇▇▇▇▇
recommendation_accuracy 0 1 92.49 4.62 85.0 88.00 92.00 97.00 100 ▇▆▆▆▆
vr_experience_quality 0 1 4.49 0.29 4.0 4.20 4.50 4.70 5 ▇▆▆▆▅
satisfaction 0 1 3.53 0.74 3.0 3.00 3.00 4.00 5 ▇▁▃▁▂

ℹ️ skimr muestra:

  • Tipo de variable. - Número de valores únicos.

  • Media y desviación estándar para numéricas.

  • Histograma en miniatura de distribución.

✍️ Nota técnica:

  • La media de satisfaction es ≈ 3.53, dentro de una escala de 1 a 5.

  • La variable tourist_rating tiene moda en valor 4.

  • Las variables accessibility, site_name, route_id, etc., tienen valores repetidos y claramente categóricos.

📝 Interpretación técnica:

  • No se detectan valores perdidos (NA) en el dataset, lo que permite aplicar análisis sin necesidad de imputación ni eliminación de registros.

7 Preparar dataset para el análisis (Tablas y Gráficos)

7.1 🛠️ Preparar dataset expandido

datos_expandido <- datos %>%
  mutate(interests = str_replace_all(interests, "\\[|\\]|‘|’|'|\"", "")) %>%
  separate_rows(interests, sep = ",\\s*") %>%
  mutate(interests = str_trim(interests)) %>%
  mutate(grupo = ifelse(accessibility, "Accesibilidad", "Sin Accesibilidad"))

head(datos_expandido, 5) # mostra las primeras 5 filas del dataframe

⛔ Aclaración metodológica:

  • La columna interests fue descompuesta mediante separate_rows() para representar cada tipo de interés como una fila independiente. Esto permitió obtener frecuencias limpias y realizar análisis por categoría individual.

⚠️ Es importante destacar que este dataset expandido (datos_expandido) no debe usarse para análisis globales, ya que un mismo turista aparece múltiples veces. Se usará solo en análisis cruzados por tipo de interés.
- Esta misma estrategia se aplicará más adelante a sites_visited, que también contiene listas multivaluadas.

ℹ️ Puedes pulsar el ícono de “flecha ▶️” en la esquina superior derecha de la tabla HTML para explorarlas.

7.2 🧮 Tabla cruzada: grupo + interés + satisfacción

tabla_interes_grupo <- datos_expandido %>%
  group_by(grupo, interests) %>%
  summarise(
    media_satisfaccion = round(mean(satisfaction, na.rm = TRUE), 2),
    n = n()
  ) %>%
  arrange(interests, desc(grupo))

kable(tabla_interes_grupo, caption = "Satisfacción media por grupo y tipo de interés") %>%
  kable_styling(full_width = FALSE)
Satisfacción media por grupo y tipo de interés
grupo interests media_satisfaccion n
Sin Accesibilidad Architecture 3.54 1001
Accesibilidad Architecture 3.54 967
Sin Accesibilidad Art 3.54 1039
Accesibilidad Art 3.51 965
Sin Accesibilidad Cultural 3.51 981
Accesibilidad Cultural 3.51 998
Sin Accesibilidad History 3.54 971
Accesibilidad History 3.53 984
Sin Accesibilidad Nature 3.56 1003
Accesibilidad Nature 3.54 1018
head(tabla_interes_grupo, 5) # mostra las primeras 5 filas del dataframe

7.3 🧮 Tabla: media de satisfacción por tipo de interés

tabla_interes_satisfaccion <- datos_expandido %>%
  group_by(interests) %>%
  summarise(
    media_satisfaccion = round(mean(satisfaction, na.rm = TRUE), 2),
    n = n()
  ) %>%
  arrange(desc(media_satisfaccion))

kable(tabla_interes_satisfaccion, caption = "Media de satisfacción por interés turístico") %>%
  kable_styling(full_width = FALSE)
Media de satisfacción por interés turístico
interests media_satisfaccion n
Nature 3.55 2021
Architecture 3.54 1968
History 3.53 1955
Art 3.52 2004
Cultural 3.51 1979
head(tabla_interes_satisfaccion, 5) # mostra las primeras 5 filas del dataframe

7.4 🧮 Tabla: sitios visitados

# Descomponer los sitios visitados
sitios_limpios <- datos %>%
  mutate(sites_visited = str_replace_all(sites_visited, "\\[|\\]|‘|’|'|\"", "")) %>%
  separate_rows(sites_visited, sep = ",\\s*") %>%
  mutate(sites_visited = str_trim(sites_visited)) %>%
  count(sites_visited, sort = TRUE)

head(sitios_limpios, 5) # presenta las primeras 5 filas del dataframe

ℹ️ La función count(sites_visited, sort = TRUE) es una otra manera de agrupar los valores para evitar duplicar los sitios visitados en los conteos.Aunque cada turista se repita en varias filas (una por cada sitio),count() agrupa por nombre del sitio (sites_visited) y cuenta cuántas veces aparece cada uno.


8 🔎 📊 Análisis exploratorio y Visualización de variables clave

8.1 🧮 Tabla de frecuencias de intereses turísticos

kable(intereses_limpios, caption = "Frecuencia de intereses turísticos (limpios)") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover"))
Frecuencia de intereses turísticos (limpios)
interests n
Nature 2021
Art 2004
Cultural 1979
Architecture 1968
History 1955

8.2 📈 Matriz de Correlación

Matriz de Correlación con la librería ggcorrplot

# Crear matriz de correlación
datos_numeric <- datos %>% select_if(is.numeric)
cor_matrix <- cor(datos_numeric, use = "complete.obs")

# Gráfico con ajustes visuales
ggcorrplot(cor_matrix,
           hc.order = TRUE,
           type = "lower",
           lab = TRUE,
           lab_size = 4,                # Aumentar tamaño texto dentro
           colors = c("red", "white", "darkgreen"),
           title = "Mapa de calor de correlaciones (variables numéricas)",
           ggtheme = theme_minimal(),
           tl.cex = 10,                 # Tamaño etiquetas en ejes
           #tl.srt = 0,                  # Etiquetas horizontales
           tl.col = "black")            # Color de etiquetas

# Guardar la gráfica en archivo PNG 
ggsave("matriz-de-correlacion-ggcorrplot.png", width = 8, height = 5, dpi = 300)

Matriz de Correlación con la librería corrplot

# Seleccionar variables numéricas
datos_numeric <- datos %>% select_if(is.numeric)

# Calcular matriz de correlación
cor_matrix <- cor(datos_numeric, use = "complete.obs")

# Crear mapa de calor con corrplot
corrplot(cor_matrix,
         method = "color",
         type = "lower",
         order = "hclust", # ordena por similitud
         tl.col = "black", # color etiquetas
         tl.cex = 0.8,     # tamaño etiquetas
         tl.srt = 45,      # inclinación
         addCoef.col = "black", # valores de correlación
         col = colorRampPalette(c("red", "white", "green"))(200),
         title = "Mapa de calor de correlaciones (corrplot)",
         mar = c(1, 1, 1, 1))  # márgenes

ℹ️ Nota: Matriz de Correlación

  • tourist_rating y satisfaction tienen una alta correlación positiva (≈ 0.85).

  • El resto de variables tienen correlaciones débiles o moderadas.

8.3 📈 Gráfico de barras de tourist_rating

Analizando la distribución de la valoración del turista, que es una variable ordinal. Esta variable será tratada como numérica en análisis inferencial, pero visualizadas como factores para claridad gráfica.

# Convertir a factor ordenado para evitar barras fuera de orden
ggplot(datos, aes(x = factor(round(tourist_rating, 1)))) +
  geom_bar(fill = "skyblue", width = 0.85) +
  labs(title = "Distribución de Tourist Rating",
       x = "Tourist Rating (redondeado)",
       y = "Frecuencia") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(size = 10, angle = 45, hjust = 0),  # Aumentar tamaño eje x
    axis.text.y = element_text(size = 12),  # Aumentar tamaño eje y
    axis.title = element_text(size = 14),
    plot.title = element_text(size = 16, face = "bold")
  )

# Guardar la gráfica en archivo PNG 
ggsave("grafico-tourist-rating.png", width = 8, height = 5, dpi = 300)

8.4 📈 Gráfico de barras de vr_experience_quality

Analizando la distribución de la calidad de la experiencia VR, que también es una variable ordinal. Esta variable será tratada como numérica en análisis inferencial, pero visualizadas como factores para claridad gráfica.

# Gráfico de barras de vr_experience_quality
ggplot(datos, aes(x = factor(vr_experience_quality))) +
  geom_bar(fill = "orange") +
  labs(title = "Distribución de Calidad de la Experiencia VR", x = "VR Quality", y = "Frecuencia")

# Guardar la gráfica en archivo PNG 
ggsave("grafico-barras-vr_experience_quality.png", width = 8, height = 5, dpi = 300)

8.5 📈 Gráfico de barras de recommendation_accuracy

Analizando la distribución de la precisión del sistema de recomendación, que es una variable continua.

ggplot(datos, aes(x = recommendation_accuracy)) +
  geom_histogram(binwidth = 5, fill = "darkgreen", color = "white") +
  labs(title = "Precisión del sistema de recomendación", x = "Porcentaje (%)", y = "Frecuencia")

# Guardar la gráfica en archivo PNG 
ggsave("grafico-barras-recommendation_accuracy.png", width = 8, height = 5, dpi = 300)

📝 Interpretación técnica:

  • Las variables tourist_rating, vr_experience_quality y recommendation_accuracy muestran distribuciones razonablemente centradas hacia valores altos.

  • Esto respalda la percepción general de buena experiencia, aunque los valores de satisfaction todavía requieren análisis más profundo.

8.6 📈 Gráfico de barras horizontales de interests

ggplot(intereses_limpios, aes(x = reorder(interests, n), y = n)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  labs(title = "Frecuencia de intereses turísticos", x = "Interés", y = "Frecuencia")

# Guardar la gráfica en archivo PNG 
ggsave("grafico-barras-horizontales-interests.png", width = 8, height = 5, dpi = 300)

📝 Interpretación técnica:

  • Los intereses más frecuentes son: Nature y Art.
  • Esto refuerza que la mayoría de turistas se orientan hacia experiencias naturales y artísticas.

8.7 Intereses cruzados con satisfacción y accesibilidad

Analizar si hay diferencias en la satisfacción media según el tipo de interés turístico y según el grupo (con/sin accesibilidad).

8.7.1 📈 Gráfico: satisfacción media por interés (ordenada)

ggplot(tabla_interes_satisfaccion, aes(x = reorder(interests, media_satisfaccion), y = media_satisfaccion)) +
  geom_col(fill = "forestgreen") +
  coord_flip() +
  labs(title = "Satisfacción media por tipo de interés", x = "Interés", y = "Media de satisfacción")

# Guardar la gráfica en archivo PNG 
ggsave("grafico-satisfacion-media-interes.png", width = 8, height = 5, dpi = 300)

📝 Interpretación técnica:

  • Algunos intereses como Nature y Architecture tienen mayor nivel medio de satisfacción.
  • Al comparar grupos, no se observan grandes diferencias de satisfacción por interés entre personas con y sin accesibilidad, pero algunas categorías muestran pequeñas variaciones que podrían explorarse más.
  • Este análisis abre la puerta a un modelo explicativo más profundo (ANOVA o regresión), aunque aquí nos centramos en descripción y comparación básica.

8.8 👱👴 Segmentación del análisis por grupo etario

# Crear rangos de edad y ubicar grupo_edad justo después de age
datos <- datos %>%
  mutate(grupo_edad = case_when(
    age < 25 ~ "Menores de 25",
    age >= 25 & age < 35 ~ "25-34",
    age >= 35 & age < 45 ~ "35-44",
    age >= 45 & age < 60 ~ "45-59",
    age >= 60 ~ "60+",
    TRUE ~ "No Especificado"
  )) %>%
  relocate(grupo_edad, .after = age)  # <- Mueve grupo_edad después de age

# Ver las primeras filas
head(datos, 10)

8.8.1 🧮 Resumen estadístico por grupo de edad

# Resumen estadístico por grupo de edad
datos %>%
  group_by(grupo_edad) %>%
  summarise(
    media_satisfaccion = round(mean(satisfaction, na.rm = TRUE), 2),
    n = n()
  ) %>%
  arrange(desc(media_satisfaccion)) %>%
  kable(caption = "Satisfacción media por grupo de edad") %>%
  kable_styling(full_width = FALSE)
Satisfacción media por grupo de edad
grupo_edad media_satisfaccion n
45-59 3.57 1407
Menores de 25 3.55 635
60+ 3.54 1029
35-44 3.51 932
25-34 3.49 997

📝 Interpretación técnica:

  • El grupo de edad con mayor satisfacción media es el de 45 a 59 años (3.57), seguido por Menores de 25 (3.55) y 60+ (3.54).
  • Aunque la diferencia entre grupos es pequeña (menos de 0.1 puntos en una escala de 1 a 5), se observa una tendencia leve de mayor satisfacción en edades intermedias y mayores.
  • Se observa un valor menor de satisfacción en las franjas etaarias de 25-34 años donde se puede personalizar las ofertas turísticas priorizando los segmentos como este, con menor nivel medio de satisfacción.
# Agrupar por interés y accesibilidad
tabla_interes_grupo <- datos_expandido %>%
  group_by(interests, grupo) %>%
  summarise(media_satisfaccion = round(mean(satisfaction), 2), .groups = "drop")

# Gráfico comparativo sin limitar eje
ggplot(tabla_interes_grupo, aes(x = media_satisfaccion, y = reorder(interests, media_satisfaccion), fill = grupo)) +
  geom_col(position = "dodge") +
  labs(title = "Satisfacción media por tipo de interés y accesibilidad",
       x = "Media de satisfacción",
       y = "Tipo de interés") +
  theme_minimal() +
  theme(axis.text = element_text(size = 10),
        legend.position = "right")

# Guardar la gráfica en archivo PNG 
ggsave("grafica-doblebarras-compartivo-accesibilidad.png", width = 8, height = 5, dpi = 300)

📝 Interpretación técnica:

  • La satisfacción media por tipo de interés se mantiene en un rango estrecho entre ~3.52 y ~3.55 en todos los casos, lo que indica experiencias positivas estables independientemente del tipo de interés turístico.
  • Los intereses que muestran ligeramente mayor satisfacción (para ambos grupos) son:Nature y Architecture
  • Las diferencias entre los grupos de Accesibilidad y Sin Accesibilidad son mínimas (inferiores a 0.02), lo cual no indica una brecha significativa en la experiencia por esta variable.
  • Esto sugiere que las condiciones de accesibilidad están bien resueltas en los contextos turísticos estudiados, al menos en relación con el tipo de interés.
  • Sin embargo, se podrían explorar más a fondo mediante un modelo explicativo (ej. regresión) si se desea identificar efectos combinados (interés × accesibilidad).

8.8.2 📈 Gráfico: Top 10 sitios turísticos más visitados

# Seleccionar los 10 sitios más visitados
sitios_top10 <- sitios_limpios %>%
  top_n(10, n) %>%
  arrange(desc(n))

# Gráfico de barras horizontales con etiquetas
ggplot(sitios_top10, aes(x = n, y = reorder(sites_visited, n))) +
  geom_col(fill = "skyblue") +
  geom_text(aes(label = n), hjust = -0.1, size = 3) +
  labs(
    title = "Top 10 sitios turísticos más visitados",
    x = "Frecuencia de visitas",
    y = "Sitio turístico"
  ) +
  theme_minimal() +
  theme(axis.text = element_text(size = 10)) +
  xlim(0, max(sitios_top10$n) * 1.1)  # Espacio para etiquetas

# Guardar la gráfica en archivo PNG 
ggsave("grafica-top-10-sitios-visitados.png", width = 8, height = 5, dpi = 300)

📝 Interpretación técnica:

  • El gráfico revela una clara preferencia por sitios emblemáticos de alto reconocimiento internacional, liderados por la Eiffel Tower (2072 visitas), Taj Mahal (2012) y el Colosseum (1994).
  • Todos los sitios del top 10 superan las 1900 visitas, lo que indica una alta concentración de interés turístico en íconos culturales y arquitectónicos.
  • La diferencia entre el primer y el décimo lugar es relativamente pequeña, lo que sugiere que la demanda está distribuida de forma bastante equilibrada entre los sitios más famosos.
  • Este patrón puede estar influido por:
  • La inclusión recurrente de estos lugares en rutas turísticas populares.
  • La alta visibilidad digital (presencia en guías, redes sociales, plataformas de reservas).
  • Su accesibilidad o fama como “destinos imperdibles”.

9 ❓ ¿La satisfacción media es significativamente mayor que 3?

Esta es la primera pregunta de investigación y esta descripta en la Parte 1 del informe.

9.1 Contexto del problema

Se analiza la satisfacción general de los turistas utilizando una escala de 1 a 5. Se desea verificar si la media poblacional supera el umbral de 3 puntos, valor considerado como referencia para experiencias positivas en este dataset.

El valor central de una escala Likert de 1 a 5 se calcula como:

\[ \mu_0 = \frac{1 + 5}{2} = 3 \]

9.2 Prueba estadística

Se aplicará una prueba t de una muestra, que evalúa si la media muestral difiere significativamente de un valor de referencia (μ₀ = 3).

Hipótesis:

> - H₀: μ ≤ 3 (la satisfacción media no supera 3)

> - H₁: μ > 3 (la satisfacción media es superior a 3)

9.3 Análisis descriptivo y gráfico

summary(datos$satisfaction)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   3.000   3.000   3.000   3.534   4.000   5.000

9.4 📊 Visualización

9.4.1 Análisis inferencial de la satisfacción turística

ggplot(datos, aes(x = satisfaction)) +
  geom_histogram(bins = 15, fill = "steelblue", color = "white") +
  geom_vline(xintercept = 3, linetype = "dashed", color = "red") +
  labs(title = "Distribución de la satisfacción turística", x = "Satisfacción", y = "Frecuencia")

# Guardar la gráfica en archivo PNG
ggsave("histograma-satisfaccion.png", width = 8, height = 5, dpi = 300)

ℹ️ Nota:

  • La mayoría de valores están entre 3 y 4.

  • La distribución está sesgada hacia valores bajos.

  • La media de satisfacción es de aproximadamente 3.53, con una desviación estándar de 1.12.

9.5 Contraste de hipótesis

# Test t de una muestra para verificar si la media de satisfacción supera 3
test_una_muestra <- t.test(datos$satisfaction, mu = 3, alternative = "greater")

# Mostramos el resultado completo
test_una_muestra
## 
##  One Sample t-test
## 
## data:  datos$satisfaction
## t = 51.321, df = 4999, p-value < 0.00000000000000022
## alternative hypothesis: true mean is greater than 3
## 95 percent confidence interval:
##  3.517076      Inf
## sample estimates:
## mean of x 
##    3.5342

📝 Interpretación técnica:

  • El test t muestra que la media observada es 3.53.
  • El p-valor es 0, por lo tanto se rechaza la hipótesis nula H₀.
  • Existe evidencia estadística suficiente para afirmar que la satisfacción media supera el valor de referencia de 3.

10 ❓¿Existen diferencias según accesibilidad?

Esta es la segunda pregunta de investigación y esta descripta en la Parte 2 del informe.

10.1 Contexto del problema

Se analiza si hay diferencias significativas entre turistas con necesidades de accesibilidad frente a quienes no requieren accesibilidad. Se comparan los valores medios de satisfacción entre estos dos grupos.

10.2 Prueba estadística

Hipótesis:

> - H₀: μ₁ = μ₂ (no hay diferencia entre ambos grupos)

> - H₁: μ₁ ≠ μ₂ (existe diferencia significativa)

10.3 Agrupamiento y estadísticos

Preparación de los grupos

datos <- datos %>%
  mutate(grupo = ifelse(accessibility, "Accesibilidad", "Sin Accesibilidad"))

10.4 Resumen estadístico por grupo

datos %>%
  group_by(grupo) %>%
  summarise(media = mean(satisfaction), sd = sd(satisfaction), n = n())

10.5 📊 Visualización comparativa

ggplot(datos, aes(x = grupo, y = satisfaction, fill = grupo)) +
  geom_boxplot() +
  labs(title = "Satisfacción por accesibilidad", x = "Grupo", y = "Satisfacción")

# Guardar la gráfica en archivo PNG
ggsave("boxplot-satisfaccion.png", width = 8, height = 5, dpi = 300)

ℹ️ Ambos grupos muestran medias similares, y rangos cercanos. No hay indicios gráficos de diferencia significativa.

10.6 Contraste de hipótesis

# Ejecutar prueba y guardar p-valor
test_dos_grupos <- t.test(satisfaction ~ grupo, data = datos)

p_valor <- signif(test_dos_grupos$p.value, 4)
media_acces <- round(mean(datos$satisfaction[datos$grupo == "Accesibilidad"]), 3)
media_sin <- round(mean(datos$satisfaction[datos$grupo == "Sin Accesibilidad"]), 3)

test_dos_grupos
## 
##  Welch Two Sample t-test
## 
## data:  satisfaction by grupo
## t = -0.65106, df = 4996.9, p-value = 0.515
## alternative hypothesis: true difference in means between group Accesibilidad and group Sin Accesibilidad is not equal to 0
## 95 percent confidence interval:
##  -0.05436677  0.02725892
## sample estimates:
##     mean in group Accesibilidad mean in group Sin Accesibilidad 
##                        3.527339                        3.540893

📝 Interpretación técnica:

  • El p-valor es 0.515, por lo tanto no se rechaza H₀.
  • No hay diferencia significativa entre los grupos con y sin accesibilidad.

11 Exportación del dataset limpio

write_csv(datos, "tourism_dataset_5000_limpio.csv")

# Generar el archivo index.html: pega esta linea de codigo en la consola:
# rmarkdown::render("actividad3_inferencial_satisfaccion-ia-v5.Rmd", output_file = "index.html")

12 🔚 Resumen técnico del análisis y recomendaciones

12.1 Cierre del análisis y reflexiones finales

Este análisis inferencial abordó dos preguntas fundamentales sobre la experiencia turística simulada:

  • ¿La satisfacción media supera el valor de referencia considerado positivo (3)?
  • ¿Existen diferencias en la satisfacción entre turistas con y sin necesidades de accesibilidad?

Para ello, se desarrolló un enfoque reproducible con R, estructurado en seis fases:


12.1.1 📊 1. Preparación y limpieza de datos

  • Se cargaron 5000 registros simulados desde el dataset de Kaggle Cultural Tourism Dataset.
  • Se aplicó normalización de nombres con janitor y se transformaron identificadores (tourist_id, route_id) en factores.
  • Las columnas multivaluadas interests y sites_visited fueron descompuestas en filas para obtener conteos precisos por tipo de interés y sitio turístico.

12.1.2 🔍 2. Exploración descriptiva y transformaciones

  • Se generaron estadísticas con skimr y gráficos con ggplot2.
  • Se creó la columna grupo_edad para análisis etario, ordenada lógicamente.
  • Las escalas ordinales (satisfaction, tourist_rating, vr_experience_quality) se trataron como cuasi-continuas para facilitar análisis paramétrico, siguiendo criterios justificados en la literatura académica (Boone & Boone, 2012).

12.1.3 🧪 3. Análisis inferencial

  • Prueba t de una muestra (media de satisfacción):

    • Resultado: p-valor extremadamente bajo (p < 0.0001), se rechaza H₀.
    • Conclusión: la satisfacción media general (≈ 3.53) es significativamente superior al umbral de referencia de 3, aunque aún lejana del máximo (5).
  • Prueba t para dos grupos independientes (accesibilidad):

    • Resultado: p-valor ≈ 0.515, no se rechaza H₀.
    • Conclusión: no existen diferencias estadísticamente significativas en la satisfacción entre turistas con y sin necesidades de accesibilidad.

12.1.4 🔗 4. Análisis correlacional

  • Se calcularon correlaciones con ggcorrplot y corrplot.
  • La variable tourist_rating muestra correlación fuerte con satisfaction (≈ 0.85).
  • La calidad de la experiencia VR (vr_experience_quality) y la precisión del sistema de recomendación (recommendation_accuracy) también presentan correlaciones positivas aunque más débiles.
  • Variables como edad, duración del tour o respuesta del sistema muestran correlaciones muy bajas con la satisfacción.

12.1.5 🔎 5. Segmentaciones y patrones específicos

  • Por grupo de edad:

    • El grupo con mayor satisfacción media fue el de 45–59 años (3.57), seguido por menores de 25 (3.55) y 60+ (3.54).
    • Se identificó una leve tendencia de mayor satisfacción en edades intermedias y mayores.
  • Por tipo de interés turístico:

    • Las categorías Nature, Architecture y History muestran mayor media de satisfacción.
    • El desglose por accesibilidad muestra valores muy similares entre ambos grupos, sin patrones fuertes diferenciadores.
  • Sitios turísticos más visitados:

    • Los 5 lugares con mayor frecuencia de visita fueron: Eiffel Tower, Taj Mahal, Colosseum, Great Wall of China y Machu Picchu.
    • Las diferencias entre ellos son pequeñas, indicando popularidad equilibrada entre íconos culturales y arquitectónicos.

12.1.6 ✅ Conclusión general

  • La experiencia turística medida por satisfacción general se percibe positivamente, aunque sin alcanzar el nivel máximo.
  • No se detectan brechas de satisfacción atribuibles a la accesibilidad, lo que sugiere que el sistema ofrece una experiencia inclusiva.
  • Los patrones observados por edad, intereses y sitios visitados permiten formular recomendaciones más específicas para futuras mejoras.

ℹ️ Para obtener mayores informaciones sobre este proyecto clique aquí y será redireccionado a la página de GitHub del curso.

ℹ️ Para acceder al análisis completo y reproducible, puede consultarse la versión online del proyecto en:


13 Referencias